package xlog

import (
	"io"
	"log"
	"os"
	"path"
	"runtime"
	"strings"
	"sync"
)

// https://github.com/appliedgocode/what
// 本库是受到上面的启发，对what库的作者有些看法不认同而修改得来

var outLog *log.Logger
var errLog *log.Logger

var rootDir string
var callerDepth = 2
var bootLock sync.Mutex
var boot bool
var silence bool

func init() {
	outLog = log.New(os.Stdout, "", log.LstdFlags)
	errLog = log.New(os.Stdout, "", log.LstdFlags)
	s := os.Getenv("XLOG_SILENCE")
	if s != "" {
		silence = true
	}
}

// Boot 在main函数中调用该方法，并且正确填写项目根目录的相对路径，否则会显示全路径
// 如果要在某个init方法中调用,则需要在匿名函数中调用, 此方法一般调用一次即可
func Boot(mainPath string, wrapDepth int, w ...io.Writer) {
	bootLock.Lock()
	defer bootLock.Unlock()
	if boot {
		return
	}
	boot = true
	if len(w) > 1 {
		outLog = log.New(w[0], "", log.LstdFlags)
		errLog = log.New(w[1], "", log.LstdFlags)
	} else if len(w) > 0 {
		outLog = log.New(w[0], "", log.LstdFlags)
		errLog = log.New(w[0], "", log.LstdFlags)
	}
	callerDepth = callerDepth + wrapDepth
	file, _, _ := fileAndLine(true)
	rootDir = path.Join(path.Dir(file))
	if mainPath != "" {
		rootDir = path.Join(rootDir, mainPath)
	}
}

func fileAndLine(isCallInInit bool, add ...int) (file string, line int, name string) {
	toAdd := 0
	if len(add) > 0 {
		toAdd = add[0]
	}
	pc, file, line, ok := runtime.Caller(callerDepth + toAdd)
	if !isCallInInit && ok && rootDir != "" {
		file = strings.TrimPrefix(file, rootDir+"/")
	}
	if ok {
		name = runtime.FuncForPC(pc).Name()
	}
	return file, line, name
}
